/*
 * Copyright 2006-2008 Michele Mostarda ( michele.mostarda@gmail.com ).
 * All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.graphnav.swing;

import org.graphnav.swing.event.EditingListener;
import org.graphnav.util.GeomUtils;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

/**
 * Defines the default <i>Arc</i> implementation.
 */
public class DefaultArc extends Arc {

    /**
     * Arrow rectangle size.
     */
    protected static final int DIRECTION_RECT_SQUARE = 6;

    /**
     * Internal constant.
     */
    protected static final int DIRECTION_RECT_SQUARE_DIV2 = DIRECTION_RECT_SQUARE / 2;

    /**
     * The renderable editor static instance.
     */
    private static final DefaultArcRenderableEditor renderableEditor = new DefaultArcRenderableEditor();

    /**
     * Node description.
     */
    private String description;

    /**
     * Node origin.
     */
    private Node fromNode;

    /**
     * Node destination.
     */
    private Node toNode;

    /**
     * Arc line.
     */
    private static final Line2D arcLine = new Line2D.Double();

    private static final Point2D.Double[] intersectionPoint =
            new Point2D.Double[] { new Point2D.Double() ,  new Point2D.Double() };

    protected static DefaultArcRenderableEditor getRenderableEditor() {
         return renderableEditor;
    }

    public DefaultArc(String description, Node fromNode, Node toNode) {
        this.description = description;
        this.fromNode    = fromNode;
        this.toNode      = toNode;
    }

    public DefaultArc(Node fromNode, Node toNode) {
         this(null, fromNode, toNode);
    }

    public Node getFromNode() {
        return fromNode;
    }

    public Node getToNode() {
        return toNode;
    }

    public String getDescription() {
        return description != null ? description : getFromNode().getDescription() + " - "  + getToNode().getDescription();
    }

    protected void setDescription(String d) {
        description = d;
    }

    public void paintShape(Graphics2D g2din, boolean selected, boolean overlapped, int detailLevel) {
        Graphics2D g2d = getGraphics2D(g2din);
        g2d.setColor(Color.RED);
        g2d.setStroke(  selected ? THICK_STROKE : THIN_STROKE );
        Point c1 = center(fromNode.getBounds2D(detailLevel));
        Point c2 = center(toNode.getBounds2D(detailLevel));
        arcLine.setLine( c1.getX(), c1.getY(), c2.getX(), c2.getY());
        g2d.draw(arcLine);

        g2d.setColor(Color.BLACK);

        //Draw direction.
        Rectangle2D toNodeBounds = toNode.getBounds2D(detailLevel);
        GeomUtils.intersectLineRectangle(
                arcLine.getX1(),
                arcLine.getY1(),
                arcLine.getX2(),
                arcLine.getY2(),
                toNodeBounds.getX(),
                toNodeBounds.getY(),
                toNodeBounds.getWidth(),
                toNodeBounds.getHeight(),
                intersectionPoint
        );
        g2d.setColor(Color.BLUE);
        g2d.fillRect(
                (int) intersectionPoint[0].getX() - DIRECTION_RECT_SQUARE_DIV2,
                (int) intersectionPoint[0].getY() - DIRECTION_RECT_SQUARE_DIV2,
                DIRECTION_RECT_SQUARE,
                DIRECTION_RECT_SQUARE
        );

        //Draw string.
        if(detailLevel == Renderable.DETAIL_LEVEL_MEDIUM) {
            int xString = (int) ( (c2.getX() - c1.getX()) / 2 + c1.getX() );
            int yString = (int) ( (c2.getY() - c1.getY()) / 2 + c1.getY() );
            g2d.setColor(Color.BLACK);
            g2d.drawString(getDescription(), xString, yString);
        }
    }

    private Point center(Rectangle2D r) {
        return new Point((int) r.getCenterX(), (int) r.getCenterY());
    }

    public RenderableEditor edit(EditingListener el) {
        DefaultArcRenderableEditor ed = getRenderableEditor();
        ed.configure(this, el);
        return ed;
    }

}
